#include "stdafx.h"
#include "DUICompat.h"
#include "Dbghelp.h"

#pragma comment(lib, "dbghelp.lib")



UINT g_nGetGadgetRectMsg = RegisterWindowMessage("WM_GETGADGETRECT");
__declspec(naked) void * __cdecl CallCDECLFunction(void * pFunction, int nParamCount, va_list list)
{
	__asm
	{
		push ebp
		mov ebp,esp
		sub esp,4h
		pushad
			xor eax,eax
			lea esi,[ebp+10h]
__cdecl_bouceback:
			cmp	eax,[ebp+0xC]
			jnb __cdecl_call

			push [esi+eax*4]
			inc eax
			jmp __cdecl_bouceback
__cdecl_call:
			call [ebp+8h]
			mov [ebp-4h],eax
			mov eax,[ebp+0xC]
			shl eax,2
			sub esp,eax
		popad
		mov eax,[ebp-4h]
		pop ebp
		leave
		retn
	}
}

__declspec(naked) void * __cdecl CallSTDCALLFunction(void * pFunction, int nParamCount, va_list list)
{
	__asm
	{
		push ebp
		mov ebp,esp
		sub esp,4h
		pushad
			xor eax,eax
			lea esi,[ebp+10h]
__stdcall_bouceback:
			cmp	eax,[ebp+0xC]
			jnb __stdcall_call

			push [esi+eax*4]
			inc eax
			jmp __stdcall_bouceback
__stdcall_call:
			call [ebp+8h]
			mov [ebp-4h],eax
		popad
		mov eax,[ebp-4h]
		pop ebp
		leave
		retn
	}
}

__declspec(naked) void * __cdecl CallTHISCALLFunction(void * pFunction, int nParamCount, va_list list)
{
	__asm
	{
		push ebp
		mov ebp,esp
		sub esp,4h
		pushad
			;;xor eax,eax
			;;inc eax
			mov eax,[ebp+0xC]
			dec eax
			mov ecx, [ebp+10h]
			mov ecx, [ecx]
			mov esi,[ebp+10h]
__thiscall_bouceback:
			cmp	eax,1
			jb __thicall_call

			push [esi+eax*4]
			dec eax
			jmp __thiscall_bouceback
__thicall_call:
			call [ebp+8h]
			mov [ebp-4h],eax
		popad
		mov eax,[ebp-4h]
		add esp,4h
		pop ebp
		retn
	}
}

int SetError(DWORD dwError)
{
	SetLastError(dwError);
	return EXCEPTION_EXECUTE_HANDLER;
}

void * CallFunction(void * pFunction, int nCallType, int nParamCount, ...)
{
	va_list list;
	va_start(list,nParamCount);
	
	SetLastError(0);
	__try 
	{
		switch(nCallType)
		{
		case CT_STDCALL:
			return CallSTDCALLFunction(pFunction,nParamCount,list);
			break;
		case CT_CDECL:
			return CallCDECLFunction(pFunction,nParamCount,list);
		case CT_THISCALL:
			if (nParamCount>=1)
				return CallTHISCALLFunction(pFunction,nParamCount,list);
			SetLastError(E_INVALIDARG);
			return 0;
			break;
		}
	}
	__except(SetError(GetExceptionCode()))
	{
		return 0;
	}
	va_end(list);

	SetLastError(E_INVALIDARG);
	return 0;
}

typedef struct tagSymbol
{
	CString szModule;
	CString szName;
	void * dwAddress;
	tagSymbol()
	{
		szModule ="";
		szName ="";
		dwAddress = 0;
	}

	tagSymbol & operator = (tagSymbol & s)
	{
		szModule = s.szModule;
		szName = s.szName;
		dwAddress = s.dwAddress;
		return *this;
	}
}mySymbol;

CArray<mySymbol,mySymbol> g_symbols;
CString g_lastModule;

void * GetSymAddress(HANDLE hProcess, LPCSTR lpSymName, LPCSTR lpModuleName=0)
{
	/*void * ret = 0;

	ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME*sizeof(TCHAR) + sizeof(ULONG64) - 1) /sizeof(ULONG64)];
	SYMBOL_INFO * psi = (SYMBOL_INFO*)buffer;
	psi->SizeOfStruct = sizeof(SYMBOL_INFO);
	psi->MaxNameLen = MAX_SYM_NAME;
	if (SymFromName(hProcess,lpSymName,psi))
	{
		ret = (void*)psi->Address;
	}

	return ret;*/
	for (int i = 0; i<g_symbols.GetSize(); i++)
	{
		mySymbol s = g_symbols.GetAt(i);
		if (lpModuleName==0)
		{
			if (s.szName == lpSymName)
			{
				TRACE("Attempting to find symbol \"%s\": SUCCESS (%08x)\r\n",lpSymName,s.dwAddress);
				return s.dwAddress;
			}
		}
		else
		{
			if (s.szName == lpSymName && s.szModule.CompareNoCase(lpModuleName)==0)
			{
				TRACE("Attempting to find symbol \"%s.%s\": SUCCESS (%08x)\r\n",lpModuleName,lpSymName,s.dwAddress);
				return s.dwAddress;
			}
		}
	}
	TRACE("Attempting to find symbol \"%s\": NOT FOUND\r\n",lpSymName);
	return 0;
}

BOOL CALLBACK EnumSymProc( 
    PSYMBOL_INFO pSymInfo,   
    ULONG SymbolSize,      
    PVOID UserContext)
{
	CArray<mySymbol,mySymbol> * m_a = (CArray<mySymbol,mySymbol> * )UserContext;
	mySymbol s;
	s.szModule = g_lastModule;
	s.dwAddress = (PVOID)pSymInfo->Address;
	s.szName = pSymInfo->Name;
	m_a->Add(s);
	//if (g_lastModule.CompareNoCase("shell32")==0)
	//	TRACE("%08X %4u %s %s\n", (DWORD)pSymInfo->Address, SymbolSize, pSymInfo->Name,g_lastModule);
    return TRUE;
}

BOOL CALLBACK EnumModules(
    LPCSTR   ModuleName, 
    DWORD64 BaseOfDll,  
    PVOID   UserContext )
{
    //TRACE("%08X %s\n", (DWORD)BaseOfDll, ModuleName);
	//if (strcmp(ModuleName,"appwiz")==0)
	{
		TRACE("Loading Symbols for %s\r\n",ModuleName);
		g_lastModule = ModuleName;
		if (!SymEnumSymbols(GetCurrentProcess(), BaseOfDll,0, EnumSymProc, UserContext))
		{
			TRACE("SymEnumSymbols failed: %d\n", GetLastError());
		}
	}
    return TRUE;
}
extern WNDPROC GetOldWindowProc();

CDUICompat::CDUICompat(HWND hWnd)
{
	HMODULE hMod = 0;
	HANDLE hProcess = GetCurrentProcess();

	m_pIdProp = 0;
	m_pChildrenProp = 0;
	m_pClassProp = 0;
	m_pContentProp = 0;

	m_pfnElementGetDataContext = 0;
	m_pfnValueZeroRelease = 0;
	m_pfnValueRelease = 0;
	m_pfnGetElementValue1 = 0;
	m_pfnGetElementValue2 = 0;
	m_pfnGetHwndElement = 0;
	m_pfnValueToString = 0;
	m_pfnInitThread1 = 0;
	m_pfnInitThread2 = 0;
	m_pfnGetGadgetRect = 0;
	m_bSymLoaded = FALSE;
	m_hMsnCore = GetModuleHandle("msncore.dll");
	m_hUxCore = GetModuleHandle("uxcore.dll");

	Value * pvStringNull = 0;
	Value * pvBoolTrue = 0;
	Value * pvBoolFalse = 0;
	Value * pvElListNull = 0;
	Value * pvElementNull = 0;
	Value * pvAtomZero = 0;
	Value * pvIntZero = 0;

	m_nElementListType = -1;
	m_nElementType = -1;
	m_nAtomType = -1;
	m_nBoolType =-1;
	m_nIntType = -1;
	m_nStringType = -1;
	m_nOffsetToValueType=4;
	m_nOffsetToValueRefCount = 8;
	m_nOffsetToValueValue=12;
	m_bOffsetHiWord = FALSE;

	CString szPath;
	DWORD dw = GetModuleFileName(GetModuleHandle("MsnCoreHelper.dll"),szPath.GetBuffer(MAX_PATH),MAX_PATH);
	szPath.ReleaseBuffer((int)dw);
	int nPos = szPath.ReverseFind('\\');
	if (nPos!=-1)
		szPath = szPath.Left(nPos+1);
	HMODULE hDbgHelp = LoadLibrary(szPath+"dbghelp.dll");
	//__HrLoadAllImportsForDll(""

	SymSetOptions(SYMOPT_EXACT_SYMBOLS|SYMOPT_DEFERRED_LOADS|SYMOPT_FAIL_CRITICAL_ERRORS/*|SYMOPT_DEBUG*/);
	if (m_hMsnCore)
		hMod = m_hMsnCore;
	if (m_hUxCore)
		hMod = m_hUxCore;
	if (hMod)
	{
		m_pfnInitThread1 = (INITTHREAD1)GetProcAddress(hMod,"?InitThread@DirectUI@@YGJI@Z");
		m_pfnInitThread2 = (INITTHREAD2)GetProcAddress(hMod,"?InitThread@DirectUI@@YGJXZ");

		m_pfnElementGetDataContext = (ELEMENTGETDATACONTEXT)GetProcAddress(hMod,"?GetDataContext@Element@DirectUI@@QAEPAUIUnknown@@PAPAVValue@2@@Z");
		m_pfnValueZeroRelease = (VALUEZERORELEASE)GetProcAddress(hMod,"?_ZeroRelease@Value@DirectUI@@AAEXXZ");
		m_pfnValueRelease = 0;
		m_pfnGetElementValue1 = (GETELEMENTVALUE1)GetProcAddress(hMod,"?GetValue@Element@DirectUI@@QBEPAVValue@2@PBUPropertyInfo@2@H@Z");
		m_pfnGetElementValue2 = (GETELEMENTVALUE2)GetProcAddress(hMod,"?GetValue@Element@DirectUI@@QAEPAVValue@2@PAUPropertyInfo@2@HPAUUpdateCache@2@@Z");
		m_pfnGetHwndElement = (GETHWNDELEMENT)GetProcAddress(hMod,"?GetElement@NativeHWNDHost@DirectUI@@QAEPAVElement@2@XZ");
		m_pfnValueToString = (VALUETOSTRING)GetProcAddress(hMod,"?ToString@Value@DirectUI@@QAEPA_WPA_WI@Z");
		if (!m_pfnValueToString)
			m_pfnValueToString = (VALUETOSTRING)GetProcAddress(hMod,"?ToString@Value@DirectUI@@QAEPAGPAGI@Z");
		m_pIdProp = *(void**)GetProcAddress(hMod,"?IDProp@Element@DirectUI@@2PAUPropertyInfo@2@A");
		m_pChildrenProp = *(void**)GetProcAddress(hMod,"?ChildrenProp@Element@DirectUI@@2PAUPropertyInfo@2@A");
		m_pClassProp = *(void**)GetProcAddress(hMod,"?ClassProp@Element@DirectUI@@2PAUPropertyInfo@2@A");
		m_pContentProp = *(void**)GetProcAddress(hMod,"?ContentProp@Element@DirectUI@@2PAUPropertyInfo@2@A");

		pvStringNull = *(Value**)GetProcAddress(hMod,"?pvStringNull@Value@DirectUI@@2PAV12@A");
		pvBoolTrue = *(Value**)GetProcAddress(hMod,"?pvBoolTrue@Value@DirectUI@@2PAV12@A");
		pvBoolFalse = *(Value**)GetProcAddress(hMod,"?pvBoolFalse@Value@DirectUI@@2PAV12@A");
		pvElListNull = *(Value**)GetProcAddress(hMod,"?pvElListNull@Value@DirectUI@@2PAV12@A");
		pvElementNull = *(Value**)GetProcAddress(hMod,"?pvElementNull@Value@DirectUI@@2PAV12@A");
		pvAtomZero = *(Value**)GetProcAddress(hMod,"?pvAtomZero@Value@DirectUI@@2PAV12@A");
		pvIntZero = *(Value**)GetProcAddress(hMod,"?pvIntZero@Value@DirectUI@@2PAV12@A");

		m_pfnGetGadgetRect = (GETGADGETRECT)GetProcAddress(hMod,"GetGadgetRect");
	}
	else if (SymInitialize(hProcess,"c:\\symbols\\"/*;SRV*c:\\symbols\\*http://msdl.microsoft.com/download/symbols"*/,TRUE))
	{
		m_bSymLoaded = TRUE;
		g_symbols.RemoveAll();

		SymEnumerateModules64(hProcess, EnumModules, &g_symbols);
		
		if (hWnd)
		{
			DWORD64 dwWndProc= (DWORD64)GetOldWindowProc();//(DWORD64)SendMessage(::FindWindow(NULL,"MsnCoreViewer"),WM_USER+3,(WPARAM)hWnd,0);////GetWindowLong(hWnd,GWL_WNDPROC);
			IMAGEHLP_MODULE64 m64 = {0};
			m64.SizeOfStruct = sizeof(m64);
			if (SymGetModuleInfo64(hProcess,dwWndProc,&m64))
			{
				CString szModuleName = m64.ModuleName;
				if (!m_pfnInitThread1 && !m_pfnInitThread2)
				{
					m_pfnInitThread1 = (INITTHREAD1)GetSymAddress(hProcess,"InitThread",szModuleName);
					m_pfnInitThread1 = (INITTHREAD1)GetSymAddress(hProcess,"DirectUI::InitThread",szModuleName);
					m_pfnInitThread1 = (INITTHREAD1)GetSymAddress(hProcess,"?InitThread@DirectUI@@YGJI@Z",szModuleName);
					m_pfnInitThread2 = (INITTHREAD2)GetSymAddress(hProcess,"?InitThread@DirectUI@@YGJXZ",szModuleName);
				}
				if (!m_pfnElementGetDataContext)
					m_pfnElementGetDataContext = (ELEMENTGETDATACONTEXT)GetSymAddress(hProcess,"?GetDataContext@Element@DirectUI@@QAEPAUIUnknown@@PAPAVValue@2@@Z",szModuleName);
				if (!m_pfnValueZeroRelease && !m_pfnValueRelease)
				{
					m_pfnValueZeroRelease = (VALUEZERORELEASE)GetSymAddress(hProcess,"?_ZeroRelease@Value@DirectUI@@AAEXXZ",szModuleName);
					m_pfnValueRelease = (VALUERELEASE)GetSymAddress(hProcess,"?Release@Value@DirectUI@@QAEXXZ",szModuleName);
				}
				if (!m_pfnGetElementValue1 && !m_pfnGetElementValue2)
				{
					m_pfnGetElementValue1 = (GETELEMENTVALUE1)GetSymAddress(hProcess,"?GetValue@Element@DirectUI@@QBEPAVValue@2@PBUPropertyInfo@2@H@Z",szModuleName);
					m_pfnGetElementValue2 = (GETELEMENTVALUE2)GetSymAddress(hProcess,"?GetValue@Element@DirectUI@@QAEPAVValue@2@PAUPropertyInfo@2@HPAUUpdateCache@2@@Z",szModuleName);
				}
				if (!m_pfnGetHwndElement)
					m_pfnGetHwndElement = (GETHWNDELEMENT)GetSymAddress(hProcess,"?GetElement@NativeHWNDHost@DirectUI@@QAEPAVElement@2@XZ",szModuleName);
				if (!m_pfnValueToString)
				{
					m_pfnValueToString = (VALUETOSTRING)GetSymAddress(hProcess,"?ToString@Value@DirectUI@@QAEPAGPAGI@Z",szModuleName);
					if (!m_pfnValueToString)
						m_pfnValueToString = (VALUETOSTRING)GetSymAddress(hProcess,"?ToString@Value@DirectUI@@QAEPA_WPA_WI@Z",szModuleName);
				}
				if (!m_pIdProp)
				{
					m_pIdProp = (void*)GetSymAddress(hProcess,"?IDProp@Element@DirectUI@@2PAUPropertyInfo@2@A",szModuleName);
					if (m_pIdProp)
					{
						m_pIdProp = *(void**)m_pIdProp;
					}
				}
				if (!m_pChildrenProp)
				{
					m_pChildrenProp = (void*)GetSymAddress(hProcess,"?ChildrenProp@Element@DirectUI@@2PAUPropertyInfo@2@A",szModuleName);
					if (m_pChildrenProp)
					{
						m_pChildrenProp = *(void**)m_pChildrenProp;
					}
				}
				if (!m_pClassProp)
				{
					m_pClassProp = (void*)GetSymAddress(hProcess,"?ClassProp@Element@DirectUI@@2PAUPropertyInfo@2@A",szModuleName);
					if (m_pClassProp)
					{
						m_pClassProp = *(void**)m_pClassProp;
					}
				}
				if (!m_pContentProp)
				{
					m_pContentProp = (void*)GetSymAddress(hProcess,"?ContentProp@Element@DirectUI@@2PAUPropertyInfo@2@A",szModuleName);
					if (m_pContentProp)
					{
						m_pContentProp = *(void**)m_pContentProp;
					}
				}
				if (!m_pfnGetGadgetRect)
					m_pfnGetGadgetRect = (GETGADGETRECT)GetSymAddress(hProcess,"__imp__GetGadgetRect@12",szModuleName);

				if (!pvStringNull)
				{
					pvStringNull = (Value*)GetSymAddress(hProcess,"?pvStringNull@Value@DirectUI@@2PAV12@A",szModuleName);
					if (pvStringNull)
						pvStringNull = *(Value**)pvStringNull;
				}
				if (!pvBoolTrue)
				{
					pvBoolTrue = (Value*)GetSymAddress(hProcess,"?pvBoolTrue@Value@DirectUI@@2PAV12@A",szModuleName);
					if (pvBoolTrue)
						pvBoolTrue = *(Value**)pvBoolTrue;
				}
				if (!pvBoolFalse)
				{
					pvBoolFalse = (Value*)GetSymAddress(hProcess,"?pvBoolFalse@Value@DirectUI@@2PAV12@A",szModuleName);
					if (pvBoolFalse)
						pvBoolFalse = *(Value**)pvBoolFalse;
				}
				if (!pvElListNull)
				{
					pvElListNull = (Value*)GetSymAddress(hProcess,"?pvElListNull@Value@DirectUI@@2PAV12@A",szModuleName);
					if (pvElListNull)
						pvElListNull = *(Value**)pvElListNull;
				}
				if (!pvElementNull)
				{
					pvElementNull = (Value*)GetSymAddress(hProcess,"?pvElementNull@Value@DirectUI@@2PAV12@A",szModuleName);
					if (pvElementNull)
						pvElementNull = *(Value**)pvElementNull;
				}
				if (!pvAtomZero)
				{
					pvAtomZero = (Value*)GetSymAddress(hProcess,"?pvAtomZero@Value@DirectUI@@2PAV12@A",szModuleName);
					if (pvAtomZero)
						pvAtomZero = *(Value**)pvAtomZero;
				}
				if (!pvIntZero)
				{
					pvIntZero = (Value*)GetSymAddress(hProcess,"?pvIntZero@Value@DirectUI@@2PAV12@A",szModuleName);
					if (pvIntZero)
						pvIntZero = *(Value**)pvIntZero;
				}
			}
		}
		
		if (!m_pfnInitThread1 && !m_pfnInitThread2)
		{
			m_pfnInitThread1 = (INITTHREAD1)GetSymAddress(hProcess,"InitThread");
			m_pfnInitThread1 = (INITTHREAD1)GetSymAddress(hProcess,"DirectUI::InitThread");
			m_pfnInitThread1 = (INITTHREAD1)GetSymAddress(hProcess,"?InitThread@DirectUI@@YGJI@Z");
			m_pfnInitThread2 = (INITTHREAD2)GetSymAddress(hProcess,"?InitThread@DirectUI@@YGJXZ");
		}
		if (!m_pfnElementGetDataContext)
			m_pfnElementGetDataContext = (ELEMENTGETDATACONTEXT)GetSymAddress(hProcess,"?GetDataContext@Element@DirectUI@@QAEPAUIUnknown@@PAPAVValue@2@@Z");
		if (!m_pfnValueZeroRelease && !m_pfnValueRelease)
		{
			m_pfnValueZeroRelease = (VALUEZERORELEASE)GetSymAddress(hProcess,"?_ZeroRelease@Value@DirectUI@@AAEXXZ");
			m_pfnValueRelease = (VALUERELEASE)GetSymAddress(hProcess,"?Release@Value@DirectUI@@QAEXXZ");
		}
		if (!m_pfnGetElementValue1 && !m_pfnGetElementValue2)
		{
			m_pfnGetElementValue1 = (GETELEMENTVALUE1)GetSymAddress(hProcess,"?GetValue@Element@DirectUI@@QBEPAVValue@2@PBUPropertyInfo@2@H@Z");
			m_pfnGetElementValue2 = (GETELEMENTVALUE2)GetSymAddress(hProcess,"?GetValue@Element@DirectUI@@QAEPAVValue@2@PAUPropertyInfo@2@HPAUUpdateCache@2@@Z");
		}
		if (!m_pfnGetHwndElement)
			m_pfnGetHwndElement = (GETHWNDELEMENT)GetSymAddress(hProcess,"?GetElement@NativeHWNDHost@DirectUI@@QAEPAVElement@2@XZ");
		if (!m_pfnValueToString)
		{
			m_pfnValueToString = (VALUETOSTRING)GetSymAddress(hProcess,"?ToString@Value@DirectUI@@QAEPAGPAGI@Z");
			if (!m_pfnValueToString)
				m_pfnValueToString = (VALUETOSTRING)GetSymAddress(hProcess,"?ToString@Value@DirectUI@@QAEPA_WPA_WI@Z");
		}
		if (!m_pIdProp)
		{
			m_pIdProp = (Value*)GetSymAddress(hProcess,"?IDProp@Element@DirectUI@@2PAUPropertyInfo@2@A");
			if (m_pIdProp)
			{
				m_pIdProp = *(void**)m_pIdProp;
			}
		}
		if (!m_pChildrenProp)
		{
			m_pChildrenProp = (Value*)GetSymAddress(hProcess,"?ChildrenProp@Element@DirectUI@@2PAUPropertyInfo@2@A");
			if (m_pChildrenProp)
			{
				m_pChildrenProp = *(void**)m_pChildrenProp;
			}
		}
		if (!m_pClassProp)
		{
			m_pClassProp = (Value*)GetSymAddress(hProcess,"?ClassProp@Element@DirectUI@@2PAUPropertyInfo@2@A");
			if (m_pClassProp)
			{
				m_pClassProp = *(void**)m_pClassProp;
			}
		}
		if (!m_pContentProp)
		{
			m_pContentProp = (Value*)GetSymAddress(hProcess,"?ContentProp@Element@DirectUI@@2PAUPropertyInfo@2@A");
			if (m_pContentProp)
			{
				m_pContentProp = *(void**)m_pContentProp;
			}
		}
		if (!m_pfnGetGadgetRect)
			m_pfnGetGadgetRect = (GETGADGETRECT)GetSymAddress(hProcess,"__imp__GetGadgetRect@12");

		if (!pvStringNull)
		{
			pvStringNull = (Value*)GetSymAddress(hProcess,"?pvStringNull@Value@DirectUI@@2PAV12@A");
			if (pvStringNull)
			{
				pvStringNull = *(Value**)pvStringNull;
			}
		}
		if (!pvBoolTrue)
		{
			pvBoolTrue = (Value*)GetSymAddress(hProcess,"?pvBoolTrue@Value@DirectUI@@2PAV12@A");
			if (pvBoolTrue)
			{
				pvBoolTrue = *(Value**)pvBoolTrue;
			}
		}
		if (!pvBoolFalse)
		{
			pvBoolFalse = (Value*)GetSymAddress(hProcess,"?pvBoolFalse@Value@DirectUI@@2PAV12@A");
			if (pvBoolFalse)
			{
				pvBoolFalse = *(Value**)pvBoolFalse;
			}
		}
		if (!pvElListNull)
		{
			pvElListNull = (Value*)GetSymAddress(hProcess,"?pvElListNull@Value@DirectUI@@2PAV12@A");
			if (pvElListNull)
			{
				pvElListNull = *(Value**)pvElListNull;
			}
		}
		if (!pvElementNull)
		{
			pvElementNull = (Value*)GetSymAddress(hProcess,"?pvElementNull@Value@DirectUI@@2PAV12@A");
			if (pvElementNull)
			{
				pvElementNull = *(Value**)pvElementNull;
			}
		}
		if (!pvAtomZero)
		{
			pvAtomZero = (Value*)GetSymAddress(hProcess,"?pvAtomZero@Value@DirectUI@@2PAV12@A");
			if (pvAtomZero)
			{
				pvAtomZero = *(Value**)pvAtomZero;
			}
		}
		if (!pvIntZero)
		{
			pvIntZero = (Value*)GetSymAddress(hProcess,"?pvIntZero@Value@DirectUI@@2PAV12@A");
			if (pvIntZero)
			{
				pvIntZero = *(Value**)pvIntZero;
			}
		}


		SymCleanup(hProcess);
	}

	if (pvBoolTrue && pvBoolFalse)
	{
		DWORD * pdwValues = (DWORD*)pvBoolTrue;
		m_nBoolType =2;
		for (int i = 0; i<4; i++)
		{
			if (HIWORD(pdwValues[i])==2)
			{
				m_nOffsetToValueType = i*4;
				m_bOffsetHiWord = TRUE;
			}
			else if (LOWORD(pdwValues[i]==2))
			{
				m_nOffsetToValueType = i*4;
				m_bOffsetHiWord = FALSE;
			}
			else if (pdwValues[i]==0xFFFFFFFF)
			{
				m_nOffsetToValueRefCount = i*4;
			}
			else if (pdwValues[i]==1)
			{
				m_nOffsetToValueValue = i*4;
				break;
			}
		}

	}

	if (pvStringNull)
	{
		m_nStringType = GetValueType(pvStringNull);
	}	
		
	if (pvElListNull)
		m_nElementListType = GetValueType(pvElListNull);
	if (pvElementNull)
	{
		m_nElementType = GetValueType(pvElementNull);
	}
		
	if (pvAtomZero)
	{
		m_nAtomType = GetValueType(pvElementNull);
	}
		
	if (pvIntZero)
		m_nIntType = GetValueType(pvIntZero);
		

	//if (hDbgHelp)
	//	FreeLibrary(hDbgHelp);
}

CDUICompat::~CDUICompat(void)
{
	if (m_bSymLoaded)	
		SymCleanup(GetCurrentProcess());

}
